A/D変換の動作確認(3)

多入力のA/D変換法について

<項目>A/D変換器のポートを選ぶ
A/D変換器の入力ポートですが、PIC16F877は、(RA0/AN0),(RA1/AN1), (RA2/AN2),(RA3/AN3),(RA5/AN4),(RE0/AN5) , (RE1/AN6) , (RE2/AN7) の全8ポートあります。ここでは、例として(RA0/AN0) ,(RA2/AN2),(RA3/AN3)を使う設定とします。「A/D変換の制御法」の表3.A/D ポートの設定表にて、A/Dポートの設定を確認します。PCFGx=「0000」のとき、全RA,および全REポートがA/D変換入力ポートとなります。また、PCFGx=「0010」のとき、全RAポートがA/D変換入力ポートとなり、REポートはディジタル入出力ポートになることが分かります。その他に、PCFGx=「1001」のとき、全RAポートとRE0ポートがA/D変換入力ポートとなり、RE1,RE2ポートはディジタル入出力ポートになることが分かります。ここでは、REポートまでA/D変換ポートにする必要性はありませんので、PCFGx=「0010」を選択します。
ここで、 「A/D変換の制御法」の表1.ADCON0レジスタの機能説明表にて、アナログチャネル指定ビットを、
CHSx=「000」とすることで、CH0(RA0)の指定になります。
CHSx=「010」とすることで、CH2(RA2)の指定になります。
CHSx=「011」とすることで、CH3(RA3)の指定になります。

<項目>A/D結果レジスタの右/左詰めについて
これまでの例と同様に、結果を右詰めにします。したがって、
ADRESH<1:0>→PortB<1:0>
ADRESL<7:0>→PortD<7:0>
という配置に出力させます。
すなわち、10ビットのMSBから順に<RB1,RB0,RD7,RD6,・・・,RD0>とします。

<項目>A/D変換のクロックの選択
「A/D変換の制御法」の表4.A/D変換用クロックの選択を参照してください。20MHzのシステムクロックでは、Fosc/32を選択することになります。よって、ADCS1=「1」,ADCS0=「0」と決まります。

<項目>ADCON0レジスタの決定
(「A/D変換の制御法」の図1. ADCON0レジスタの構成を参照してください)

CH0(RA0)の場合(初期設定時)

ということで、ADCON0→B’10000000’ (80H)


CH2(RA2)の場合(初期設定時)

ということで、ADCON0→B’10010000’ (90H)


CH3(RA3)の場合(初期設定時)

ということで、ADCON0→B’10011000’ (98H)


<項目>ADCON1レジスタの決定
(「A/D変換の制御法」の図2. ADCON1レジスタの構成を参照してください)

ADCON1レジスタの内容の決定

ということで、ADCON1→B’10000010’ (82H)


<項目>ハード側の接続について
A/D変換の結果を簡単に確認するためLEDを接続し点灯させます。LEDの接続ポートですが、先ほどの例のように私のターゲットボードでは、PortBとPortDが隣り合って並んでいますので、図1のように10ビットのMSBから順に<RB1,RB0,RD7,RD6,・・・,RD0>と接続します。
また、A/D変換入力ポートは3つありますので、RCポートのLEDを点灯させることで、どのポートでA/D変換が行われているかを確認できるようにしました。すなわち、CH0のときがRC0、CH2のときがRC2、CH3のときがRC3ポートのLEDを点灯するようにします。
A/D変換入力の3端子ですが、簡単のためそれぞれ10kΩの可変抵抗を接続し、0〜5Vの可変電圧を入力できるようにしました。アナログソースの最大推奨インピーダンスは 10kΩですから、それより大きい抵抗値は好ましくありません。

多入力A/D変換の動作確認回路
図1.多入力A/D変換の動作確認回路

アナログ入力端子ですが、テスタなどを接続してアナログの電圧値が分かるようにします。また、アナログ入力電圧が安定しない場合には、10kΩの可変抵抗に 0.1μF程度のセラミックコンデンサを接続するとよいでしょう。


<項目>多入力A/D変換動作の確認プログラム
図2に複数入力のA/D変換動作のフローチャートを示します。
プログラムの解説については、「プログラムの説明(3)」の項をご参照ください。

A/D変換プログラム(3)のフローチャート
A/D変換プログラム(3)のフローチャート

図2.A/D変換プログラム(3)
フローチャート

(注)以下に示すプログラムには、ホームページ画面作成の都合上、空白として全角文字のスペースなどが挿入されています。したがって、下記プログラムリストをそのままコピーしてMPLABのソースファイルとされた場合には、エラーとなることがあります。

→ここをクリックして、下記のプログラムをダウンロードするようにしてください。
<ダウンロードする>  ファイル名:「adconv3.asm」 サイズ5.40kバイト

→ここをクリックして、下記のオブジェクトファイルをダウンロードするようにしてください。
<ダウンロードする>  ファイル名:「adconv3.hex」 サイズ484バイト

;***********************************************************
; A/D変換動作チェックプログラム(3)
; A/D変換入力 3端子(CH0/RA0),(CH2/RA2),(CH3/RA3)
; A/D変換の結果は LED 点灯により確認
; RB1(MSB),RB0,RD7,RD6,RD5,RD4,RD3,RD2,RD1,RD0(LSB)
; の10ビット
; 3入力の CH 判別は LED 点灯により確認
; CH0 → RC0 を点灯
; CH2 → RC2 を点灯
; CH3 → RC3 を点灯
; A/D 割り込みは使用せず、簡単のため GO ビットで判断
;***********************************************************
    LIST   P=PIC16F877
    INCLUDE  P16F877.INC

;(1)プロセッサの種別指定
;(2)インクルードファイルの指定

;***********************************************************
; 変数定義とレジスタ割付
;***********************************************************
COUNT EQU 20H
COUNT1 EQU 21H
COUNT2 EQU 22H
COUNT3 EQU 23H
COUNT4 EQU 24H
PC_LOC EQU 25H

ORG 0

;(3)ループカウンタ
;   ループカウンタ1
;   ループカウンタ2
;   ループカウンタ3
;   ループカウンタ4
;   ロケーションカウンタ

;(4)プログラムの開始番地の指定

;***********************************************************
; 入出力ピン初期化
;***********************************************************
    BSF    STATUS,RP0
    MOVLW   B'10000010'
    MOVWF   ADCON1
    CLRF   TRISB
    CLRF   TRISC
    CLRF   TRISD
    BCF    STATUS,RP0

    MOVLW   B'10000000'
    MOVWF   ADCON0
    MOVLW   B'10010000'
    MOVWF   ADCON0
    MOVLW   B'10011000'
    MOVWF   ADCON0

;(5)Bank 1 へ切替
;(6)RA0〜5アナログ、結果右詰
;(7)ADCON1レジスタの設定
;(8)PortB 出力モードに設定
;   PortC 出力モードに設定
;   PortD 出力モードに設定
;(9)Bank 0 へ戻す
;
;(10)Fosc/32,CH0 設定, A/D off
;(11)ADCON0レジスタの設定
;(10)Fosc/32,CH2 設定, A/D off
;(11)ADCON0レジスタの設定
;(10)Fosc/32,CH3 設定, A/D off
;(11)ADCON0レジスタの設定

;***********************************************************
; メインプログラム
;***********************************************************
MAIN
    MOVLW   3
    MOVWF   PC_LOC

ADSTART
    MOVF   PC_LOC,W
    CALL   SELECT_LED
    MOVWF   PORTC

    MOVF   PC_LOC,W
    CALL   SELECT_AD
    MOVWF   ADCON0

    CALL   TIME_ACQ
    BSF    ADCON0,GO
WAIT
    BTFSC   ADCON0,GO
    GOTO   WAIT
    MOVF   ADRESH,W
    MOVWF   PORTB
    BSF    STATUS,RP0
    MOVF   ADRESL,W
    BCF    STATUS,RP0
    MOVWF   PORTD
    CALL   TIME1S

    DECFSZ  PC_LOC,F
    GOTO   ADSTART
    GOTO   MAIN


;(12)ロケーションカウンタの初期値
;   ロケーションカウンタの設定


;(13)ロケーションカウンタをWregにロードする
;(14)CH 表示の判別サブルーチンへ
;(15)PortCへ CH 判別データを出力
;
;(16)ロケーションカウンタをWregにロードする
;(17)CH 設定サブルーチンへ
;(18)ADCON0レジスタの設定
;
;(19)20μs 一定時間待つ(アクィジション時間)
;(20)A/D スタート
;(21)A/D が完了すると GOが0になる
;(22)GO が 0 だったらループから抜ける
;   GO が 1 だったら WAIT へループする
;(23)A/D データ上位(データは右詰)
;(24)PortBへ A/D 結果を出力
;(25)Bank 1 へ切替
;(26)A/D データ下位
;(27)Bank 0 へ戻す
;(28)PortDへ A/D 結果を出力
; (29)1秒間 表示

; (30)ロケーションカウンタ−1
;   A/D 変換を繰り返す
;   ロケーションカウンタ 2→1→0

;***********************************************************
; CH 表示の判別サブルーチン
;***********************************************************
SELECT_LED
    ADDWF   PCL,F
    NOP
    RETLW   B'00001000'
    RETLW   B'00000100'
    RETLW   B'00000001'


;(31)プログラムカウンタ+ロケーションカウンタ
;(32)ダミー行
;(33)CH3 表示のデータを Wregにロード
;(34)CH2 表示のデータを Wregにロード
;(35)CH0 表示のデータを Wregにロード

;***********************************************************
;A/D CH設定のサブルーチン
;***********************************************************
SELECT_AD
    ADDWF   PCL,F
    NOP
    RETLW   B'10011001'
    RETLW   B'10010001'
    RETLW   B'10000001'


;(36)プログラムカウンタ+ロケーションカウンタ
;(37)ダミー行
;(38)Fosc/32,CH3 設定, A/D on を Wregにロード
;(39)Fosc/32,CH2 設定, A/D on を Wregにロード
;(40)Fosc/32,CH0 設定, A/D on を Wregにロード

;***********************************************************
;遅延サブルーチン
;***********************************************************
;アクィジション時間(20μs)の遅延サブルーチン(20MHzクロック時)
TIME_ACQ
    MOVLW   20H
    MOVWF   COUNT
    NOP
LOOP_ACQ
    DECFSZ  COUNT,F
    GOTO   LOOP_ACQ
    RETURN



;(41)1サイクル 20H = 32
;(42)1サイクル
;(43)1サイクル 微調整ダミー

;(44)1×(32-1)+2 = 33サイクル
;(45)2×(32-1) = 62サイクル
;(46)2サイクル
; 合計 100サイクル×0.2μs = 20μs

;100μs遅延サブルーチン(20MHzクロック時)
TIME100
    MOVLW   0A5H
    MOVWF   COUNT
    NOP
    NOP
LOOP
    DECFSZ  COUNT,F
    GOTO   LOOP
    RETURN



; 1サイクル A5H=165
; 1サイクル
; 1サイクル 微調整ダミー
; 1サイクル 微調整ダミー

; 1×(165-1)+2 = 166サイクル
; 2×(165-1) = 328サイクル
; 2サイクル
; 合計 500サイクル×0.2μs = 100μs

;10ms遅延サブルーチン(20MHzクロック時)
TIME10M
    MOVLW   63H
    MOVWF   COUNT1
    NOP
    NOP
LOOP1
    CALL   TIME100
    DECFSZ  COUNT1,F
    GOTO   LOOP1
    RETURN



; 1サイクル 63H=99
; 1サイクル
; 1サイクル 微調整ダミー
; 1サイクル 微調整ダミー

; (2+500)×99=49698サイクル
; 1×(99-1)+2 = 100サイクル
; 2×(99-1) = 196サイクル
; 2サイクル
; 合計 50000サイクル×0.2μs = 10ms

;1s遅延サブルーチン(20MHzクロック時)
TIME1S
    MOVLW   63H
    MOVWF   COUNT2
    MOVLW   62H
    MOVWF   COUNT3
    MOVLW   03H
    MOVWF   COUNT4
    NOP
LOOP2
    CALL   TIME10M
    DECFSZ  COUNT2,F
    GOTO   LOOP2
LOOP3
    CALL   TIME100
    DECFSZ  COUNT3,F
    GOTO   LOOP3
LOOP4
    DECFSZ  COUNT4,F
    GOTO   LOOP4
    RETURN

    END

; 1サイクル 63H=99
; 1サイクル
; 1サイクル 62H=98
; 1サイクル
; 1サイクル 03H=3
; 1サイクル
; 1サイクル 微調整ダミー

;(2+50000)×99=4950198サイクル
; 1×(99-1)+2 = 100サイクル
; 2×(99-1) = 196サイクル

;(2+500)×98=49196
; 1×(98-1)+2 = 99サイクル
; 2×(98-1) = 194サイクル

; 1×(3-1)+2 = 4サイクル
; 2×(3-1) = 4サイクル
; 2サイクル
; 合計 5000000サイクル×0.2μs = 1s

【プログラムの説明(3)】ここがポイント
このプログラムについて、順を追って解説を加えておきましょう。

(1)プロセッサの種別指定
定義の仕方は「PROCESSOR」か「LIST」命令を使って設定します。ここで指定するプロセッサ名称は、パッケージの種類を示すサフィックス(最後の英記号の部分)は不要です。

   PROCESSOR  PIC16F877
    または
   LIST  P=PIC16F877

(2)標準ヘッダーファイルのインクルード
標準ヘッダーファイルとは、各プロセッサが持っているSFR(Special Function Register)をラベル(記号)で使える様にするため、ラベルとハードウェアの場所とを定義しているファイルです。標準ヘッダーファイルは 「プロセッサ名.INC」というファイル名で統一されて、MPLABのディレクトリに格納されています。従って、これのインクルード方法は下記のようにして行います。
一度、参考までに標準ヘッダーファイルの内容をエディタ等で見ておくことをお勧めします。

   INCLUDE    P16F877.INC
    または
   #INCLUDE   P16F877.INC

(3)変数定義とレジスタ割付
レジスタファイルアドレスを指定するときに、アドレス数値を直接指定することもできますが、数値だけでは間違いも多く、プログラム自身も分かりにくくなってしまいます。そこで、EQU命令などを使ってラベルを設定し変数を定義します。レジスタファイルアドレスは、7ビットあるので、00〜7Fまで最大128個のレジスタが指定できますが、実際に物理的に実装されて汎用的に使用できるレジスタ数はデバイスによって異なっていますので注意が必要です。
PIC16F877の汎用レジスタのアドレスは、20H〜7FH
となっていますので、20H以降のアドレスに割り付けます。

(4)プログラムの開始番地の指定
「ORG」はプログラムの開始番地を指定する擬似命令で、ORG以下の実際のプログラム命令が格納されるプログラムメモリ内の位置(アドレス)を指定します。

   ORG  0  ;0番地から格納することを示します。

コンピュータは一般に電源投入時やリセットをすると必ず0番地からスタートするようになっているので、0番地には必ず命令があることが必要です。

(5)Bank 1 へ切替
PICには各種の動作モードを設定するための Special Register と呼ばれるものが用意されています。PICを動作させるためには、まずこのSpecial Registerの設定から始めます。そしてそれらは全て、Register File と呼ぶメモリとして用意されています。その Register Fileは Bank0, Bank1, Bank2, Bank3 とよばれるアドレス空間をもっているため、多少アクセスの仕方が面倒です。つまりRESET後の通常はBank0となっているので、Bank1側のレジスタにアクセスするときはBankの切替えをしてからとなります。またBank0とBank1に同じ物があるときにはどちらでも同じ様に使えます。
Bank1へ切り替える方法ですが、「STATUS」レジスタにある2ビットのRP0、RP1を変えてBankを指定します。デフォルトは、Bank0です。表1にBankとRP1,RP0ビットとの関係を示します。Bank1へ切り替えるためには、RP0ビットを「1」にします。(RP1はデフォルトで「0」なので変える必要はない。)

 BSF    STATUS,RP0
「STATUS」レジスタのRP0ビットを「1」にする。

表1.BankとRP1,RP0ビットとの関係
Bank RP1 RP0


(6)RA0〜RA5のポートをアナログ、結果右詰
A/D変換器の入力ポートとして、(RA0/AN0),(RA2/AN2),(RA3/AN3)を使います。ここで、「A/D変換の制御法」の表3.A/D ポートの設定表にて、A/Dポートの設定を確認します。PCFGx=「0010」のとき、RA0〜RA5のポートがA/D変換入力ポートとなり、REポートはディジタル入出力ポートになることが分かります。A/D 結果フォーマットは右詰に設定します。

bit7: A/D 結果フォーマットセレクト:右詰=「1」
bit6: 機能なし(とりあえず「0」とでもしておく)
bit5: 機能なし(とりあえず「0」とでもしておく)
bit4: 機能なし(とりあえず「0」とでもしておく)
bit3: PCFG3=「0」
bit2: PCFG2=「0」
bit1: PCFG1=「1」
bit0: PCFG0=「0」
ということで、B’10000010’ (82H)をWregにロードする。


(7)ADCON1レジスタの設定
Wregの内容をADCON1レジスタに上書きする。


(8)PortB,C,Dを 出力モードに設定
TRISB,TRISC,およびTRISDレジスタは、CLRF(fレジスタをゼロクリアする命令)で出力設定となります。

 CLRF   TRISB
「TRISBレジスタをゼロクリアする。すなわち、PORTB全ポートを出力に設定する」

 CLRF   TRISC
「TRISCレジスタをゼロクリアする。すなわち、PORTC全ポートを出力に設定する」

 CLRF   TRISD
「TRISDレジスタをゼロクリアする。すなわち、PORTD全ポートを出力に設定する」

なお、PortAの設定ですが、デフォルトがA/D入力ポートになりますので省略できます。


(9)Bank 0 へ戻す
動作モードの設定後は、Bank0に戻しておきます。Bank1へ切り替えるためには、RP0ビットを「0」にします。(RP1はデフォルトで「0」なので変える必要はない。)

BCF    STATUS,RP0
「STATUS」レジスタのRP0ビットを「0」にする。すなわち、Bank0に戻す。」


(10)Fosc/32,CH 設定,A/D off
「A/D変換の制御法」の表4.A/D変換用クロックの選択を参照してください。内部RC発振回路を使用するFrc指定の場合は、システムクロックには影響されず、2〜6μsの周波数になりますが、正確なクロック周波数ではなくなります。そこで、Fosc/2,Fosc/8,Fosc/32のどれかを選ぶことになります。システムクロックの周波数により、指定できる範囲が限られていますので注意が必要です。正しいA/D 変換のためには、必ずA/D 変換クロック(TAD)を、最小TAD 時間の1.6μs以上にする必要がありました。
20MHzのシステムクロックでは、Fosc/32を選択することになります。
また、「A/D変換の制御法」の表1.ADCON0レジスタの機能説明表を参照してください。

ここがポイントアナログチャネル指定ビットですが、

CHSx=「000」とすることで、CH0(RA0)の指定になります。

ということで、ADCON0→B’10000000’ (80H)


CHSx=「010」とすることで、CH2(RA2)の指定になります。

ということで、ADCON0→B’10010000’ (90H)


CHSx=「011」とすることで、CH3(RA3)の指定になります。

ということで、ADCON0→B’10011000’ (98H)


(11)ADCON0レジスタの設定
Wregの内容をADCON0レジスタに上書きする。

(12)ロケーションカウンタの初期値設定
ここで、ロケーションカウンタを設定したのは、「CH 表示の判別サブルーチン」や、「A/D CH設定のサブルーチン」のところで、PCレジスタにこのロケーションカウンタの数字を加え、相当するロケーションへジャンプさせるためです。ジャンプ先には、それぞれCH 表示のデータや、A/D CH設定のデータを記載しておき、そのデータをRETLW命令を使ってWregに読み込んでリターンします。このロケーションカウンタは、「PC_LOC」という変数に入れておきます。

(13)ロケーションカウンタをWregにロードする
「PC_LOC」という変数に入っているロケーションカウンタ値をWregにロードします。

(14)CH 表示の判別サブルーチンへジャンプする
サブルーチンの内容の詳細は、「CH 表示の判別サブルーチン」の説明を見てください。

(15)PortCへ CH 判別データを出力
「CH 表示の判別サブルーチン」で、CH判別データがWregに格納されてきます。そのCH判別データをPortCへ出力し、データに対応するLEDが点灯します。

(16)ロケーションカウンタをWregにロードする
「PC_LOC」という変数に入っているロケーションカウンタ値をWregにロードします。

(17)CH 設定サブルーチンへジャンプする
サブルーチンの内容の詳細は、「CH 設定サブルーチン」の説明を見てください。

(18)ADCON0レジスタの設定
「CH 設定サブルーチン」で、設定データがWregに格納されてきます。
ここで、WregのデータをADCON0レジスタに移して設定します。

(19)20μs 一定時間待つ
PICでは、A/D変換をするために、まずアナログ信号を一旦内部のコンデンサに蓄えます。その後、参照となる一定の電圧を加算して比較しながら計測するという逐次変換方式であるため、A/D変換を正確に行うためには、蓄積するまでの時間(アクィジション時間)が必要です。

ここがポイント
10ビットではアクィジション時間=20μs
になります。

ここで、アクィジション時間(20μs)の遅延サブルーチンにジャンプします。

(20)A/D スタート
ADCON0レジスタのGOビットをセットすると、A/D変換が開始されます。

BSF    ADCON0,GO
「ADCON0」レジスタのGOビットを「1」にする。すなわち、A/D変換を開始する。」

(21)A/D が完了すると GOビットが0になる
A/D変換を開始してから12TADの変換時間すなわち、12×1.6μs=19.2μs必要となります。A/Dが完了するとGOビットが「0」となりますので、時間で確認す
る必要はありません。

(22)GOビットが 0 だったらループから抜ける。
    GO が 1 だったら WAIT へループする
A/D変換が完了するとGOビットが「0」となり、次の命令で分岐されます。
BTFSC   ADCON0,GO
「ADCON0」レジスタのGOビットが「0」だったら次の命令をスキップし、ループから抜けます。
GOTO   WAIT
ただし、A/D変換が終了しない間は、「ADCON0」レジスタのGOビットが「1」のままですので、WAITラベルへ戻ってループを繰り返します。

(23)A/D データ上位(データは右詰)
MOVF   ADRESH,W
「ADRESH」レジスタの内容をWregに上書きする。
データは右詰ですので、ADRESHの<1:0>ビットに上位データが入り、他のビットは「0」が入ります。

(24)PortBへ A/D 結果を出力
Wregのデータは、ADRESHレジスタの値ですので、PortBの<1:0>ビットに上位データが出力され、他のビットは「0」となります。LEDは「1」となったビットで点灯します。
MOVWF  PORTB
「PORTBへWregのデータを出力します。」

(25)Bank 1 へ切替
ADRESLレジスタは、Bank1にありますのでBankを切り替える必要があります。

(26)A/D データ下位
MOVF   ADRESL,W
「ADRESL」レジスタの内容をWregに上書きする。

(注)もしBank1への切り替えを忘れて(Bank0のままで)、この命令を行った場合には、ADRESHレジスタの内容がWregに入ってしまいます。

(27)Bank 0 へ戻す
「ADRESL」レジスタの内容をWregに移したら、Bank0に戻しておきましょう。

(28)PortDへ A/D 結果を出力
Wregのデータは、ADRESLレジスタの値ですので、PortDに下位データが出力されます。LEDは「1」となったビットで点灯します。
MOVWF  PORTD
「PORTDへWregのデータを出力します。」

(29)1秒遅延サブルーチンへ
ここでは、3入力にそれぞれ対応してLED点灯するA/D変換結果を、「目で見て」確認するため、1秒間待ちます。もし、LED表示の間隔がまだ短い(数秒にしたい)と感じたら、このCALL命令をいくつか記述してください。

(30)ロケーションカウンタ−1、 A/D 変換を繰り返す 
「PC_LOC」という変数に入っているロケーションカウンタ値を−1します。
次の命令で「ADSTART」のラベルまで戻り、A/D変換動作を繰り返す。
ただし、ロケーションカウンタが、2→1→0となったときには、次の命令を飛ばして
GOTO MAINにて、「MAIN」のラベルまで戻り、A/D変換動作を繰り返します。

【CH 表示の判別サブルーチンの説明】
(31)プログラムカウンタ+ロケーションカウンタ 

ここがポイントプログラムカウンタのPCLレジスタに、ロケーションカウンタ(Wregに入っている)を足すことで、次の命令をジャンプさせることができます。

たとえば、足されるロケーションカウンタ値が3であったならば、次に実行される命令は(32)ではなく(35)の行にジャンプします。

(32)ダミー行
(30)のところで、ロケーションカウンタ−1されて「0」となったときには、(12)で「3」に戻されます。したがって、このサブルーチン内では、ロケーションカウンタ値は「3」,「2」,「1」の3種類になります。ロケーションカウンタ値として「0」はありませんので、この行は実行されません。ダミーとして「NOP命令(何もしない)」を入れておきます。

(33)CH3 表示のデータを Wregにロードして戻る
3つのA/D変換入力ポートを使うため、どのポートのA/D変換結果なのか、RCポートのLEDを点灯させることでを確認しています。
ここではCH3のとき、RCポートの3ビット目を「1」とする設定にします。

RETLW   B'00001000'
Wregに、3ビット目が「1」のリテラルデータを持って戻る。

(34)CH2 表示のデータを Wregにロードして戻る
ここではCH2のとき、RCポートの2ビット目を「1」とする設定にします。

RETLW   B'00000100'
Wregに、2ビット目が「1」のリテラルデータを持って戻る。

(35)CH0 表示のデータを Wregにロードして戻る
ここではCH0のとき、RCポートの0ビット目を「1」とする設定にします。

RETLW   B'00000001'
Wregに、0ビット目が「1」のリテラルデータを持って戻る。


【A/D CH設定のサブルーチンの説明】
(36)プログラムカウンタ+ロケーションカウンタ 
(31)のところで解説した内容と同じです。プログラムカウンタのPCLレジスタに、ロケーションカウンタ(Wregに入っている)を足すことで、次の命令をジャンプさせることができます。

(37)ダミー行
(32)のところで解説した内容と同じです。このサブルーチン内では、ロケーションカウンタ値は「3」,「2」,「1」の3種類になります。ロケーションカウンタ値として「0」はありませんので、この行は実行されません。ダミーとして「NOP命令(何もしない)」を入れておきます。

(38)Fosc/32,CH3 設定, A/D on を Wregにロードして戻る
3つのA/D変換入力ポートを使うため、各ポートのADCON0レジスタの設定データをWregにロードします。

ここでは、CH3(RA3)のADCON0レジスタの設定データをロードします。

ということで、Wregに B’10011001’ (99H)のリテラルデータを持って戻る。


(39)Fosc/32,CH2 設定, A/D on を Wregにロードして戻る

ここでは、CH2(RA2)のADCON0レジスタの設定データをロードします。

ということで、Wregに B’10010001’ (91H)のリテラルデータを持って戻る。


(40)Fosc/32,CH0 設定, A/D on を Wregにロードして戻る

ここでは、CH0(RA0)のADCON0レジスタの設定データをロードします。

ということで、Wregに B’10000001’ (81H)のリテラルデータを持って戻る。


【20μs遅延サブルーチンの説明】

アクィジション時間(20μs)の遅延サブルーチン
(41)ループ回数(20H=32回)をWregにロードする。
(42)Wregの内容をfレジスタ(COUNT)に入れる
(43)サイクル数をちょうど100にするために、
  1サイクル分のNOP命令(何もしないダミー)を入れた。
(44)fレジスタ(COUNT)の減算をし、結果が0なら次の命令をスキップする。
  0以外である(32−1)回分は、1サイクル。
  最後0になってスキップするとき2サイクル。
(45)(32−1)回分は、2サイクル
(46)サブルーチンから無条件復帰するとき、2サイクル
よって、計100サイクルになり、20MHzクロックでは、1サイクル0.2μsであることから、100サイクル×0.2μs=20μsになります。

その他の遅延サブルーチン
100μs,10ms,1s遅延サブルーチンの解説は、ここをクリックしてください。


<項目>A/D変換動作の確認
図3(a)に、A/D変換結果を表示するLED点灯の様子を示します。私のターゲットボードでは、PortBとPortDが隣り合って並んでいますので、10ビットの結果を右詰めに表示しています。したがって、
ADRESH<1:0>→PortB<1:0>
ADRESL<7:0>→PortD<7:0>
という配置に出力させます。
すなわち、10ビットのMSBから順に<RB1,RB0,RD7,RD6,・・・,RD0>となっています。
結果のビットですが、「1」のとき点灯し、「0」のとき消灯しています。
また、A/D変換入力ポートは3つありますので、RCポートのLEDを点灯させることで、どのポートでA/D変換が行われているかを確認できるようにしました。すなわち、CH0のときがRC0、CH2のときがRC2、CH3のときがRC3ポートのLEDを点灯するようにします。図3(b)に、各A/D変換入力ポートに対応するLED点灯の様子を示します。

A/D変換結果を表示するLED点灯の様子
図3(a).A/D変換結果を表示する
      LED点灯の様子
各A/D変換入力ポートに対応するLED点灯の様子
図3(b).各A/D変換入力ポートに
      対応するLED点灯の様子

それでは、ターゲットボード上のLED点灯の結果から、ちゃんと動作しているかどうかチェックしていきましょう。表2に多入力のA/D変換結果をまとめてみました。
理論値の計算ですが、5V時の実測データ(4.97V)と、各電圧の実測データから次のように計算できます。(数字は10進表示、端数は四捨五入)
3V時は、1023×(3.001V/4.97V)=618
2V時は、1023×(2.003V/4.97V)=412
1V時は、1023×(1.004V/4.97V)=207

表2で、ターゲットボードの値と理論値を比べてみると、1LSB程度の誤差があるものの、A/D変換動作が確認されました。

表2.多入力A/D変換の結果
A/D変換
入力CH
RCポートの
点灯ビット
入力電圧
( )内は実測値
出力結果
ターゲットボード 理論値
2進 16進 10進 2進 16進 10進
RC0 1V
(1.004V)
B’0011001110’ H’0CE’ D’206’ B’0011001111’ H’0CF’ D’207’
RC2 2V
(2.003V)
B’0110011100’ H’19C’ D’412’ B’0110011100’ H’19C’ D’412’
RC3 3V
(3.001V)
B’1001101001’ H’269’ D’617’ B’1001101010’ H’26A’ D’618’


次へは、「PICのA/D変換の分解能の向上」について解説します


<前ページへ> <次ページへ>
<TOPページへ>



テレワークならECナビ Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!
無料ホームページ 無料のクレジットカード 海外格安航空券 海外旅行保険が無料! 海外ホテル